#include <stdint.h>
#include <stdio.h>
#include <string>
#include <vector>

#include <hilog/log.h>
#include <js_native_api.h>
#include <napi/native_api.h>
#include <node_api.h>

#include "native_common.h"


#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0x0032
#define LOG_TAG "React Native Napi"

static napi_value add(napi_env env, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "React Native  Add");
  size_t requireArgc = 2;
  size_t argc = 2;
  napi_value args[2] = {nullptr};
  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
  napi_valuetype valuetype0;
  napi_typeof(env, args[0], &valuetype0);
  napi_valuetype valuetype1;
  napi_typeof(env, args[1], &valuetype1);
  double value0;
  napi_get_value_double(env, args[0], &value0);
  double value1;
  napi_get_value_double(env, args[1], &value1);
  napi_value sum;
  napi_create_double(env, value0 + value1, &sum);
  return sum;
}

static napi_value napiRunScriptFromArrayBuffer(napi_env env, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "React Native napiRunScriptFromArrayBuffer");
  napi_value arraybuffer, result;
  size_t argc = 1;
  char buffer[5*1024*1024] = {'\0'};
  void* data = buffer;  
  size_t length = 0;
    
  NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &arraybuffer, NULL, NULL));   
  NAPI_CALL(env, napi_get_arraybuffer_info(env, arraybuffer, &data, &length));    
  napi_value scriptValue;  
  NAPI_CALL(env, napi_create_string_utf8(env, (const char*)data, length, &scriptValue));
  NAPI_CALL(env, napi_run_script(env, scriptValue, &result));
  return result;
}

static napi_value napiRunScriptFromFilePath(napi_env env, napi_callback_info info) {
  OH_LOG_INFO(LOG_APP, "React Native napiRunScriptFromFilePath");
  napi_value filePath, result;
  size_t argc = 1;
  const size_t size =  1024;
  size_t length = 0;
  char path[size] = {'\0'};
    
  NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &filePath, NULL, NULL));
  NAPI_CALL(env, napi_get_value_string_utf8(env, filePath, path, size, &length));   
  if (length > 1024) {
    OH_LOG_ERROR(LOG_APP, "React Native napiRunScriptPath path too long");
  }
    
  OH_LOG_INFO(LOG_APP, "React Native napiRunScriptFromFilePath path: %{public}s", path);
  napi_run_script_path(env, path, &result);
  return result;
}

//static napi_value testGetPrototype(napi_env env, napi_callback_info info) {
//  OH_LOG_ERROR(LOG_APP, "React Native  testGetPrototype");
//  size_t argc = 1;
//  napi_value args[1], result;
//  NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
//  NAPI_CALL(env, napi_get_prototype(env, args[0], &result));
//  return result;
//}

// static napi_value testNapiRunAbc(napi_env env, napi_callback_info info) {
//    OH_LOG_ERROR(LOG_APP, "React Native testNapiRunAbc");
//    std::vector<uint8_t> buffer;
//    FILE *fp = nullptr;
//    char s;
//    fp =
//    fopen("/data/accounts/account_0/applications/com.example.l2demo/com.example.l2demo/game.abc",
//    "r"); if (fp) {
//        OH_LOG_ERROR(LOG_APP, "React Native  fp open success");
//        while(fscanf(fp, "%c", &s) == 1) {
//            buffer.push_back(s);
//        }
//    } else {
//        OH_LOG_ERROR(LOG_APP, "React Native  fp open fail");
//    }
//    OH_LOG_ERROR(LOG_APP, "React Native buffer size = %{public}d", buffer.size());
//    napi_value execScriptResult = nullptr;
//    napi_run_buffer_script(env, buffer, &execScriptResult);
//    OH_LOG_ERROR(LOG_APP, "React Native testNapiRunAbc end");
//    return nullptr;
//}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
  OH_LOG_INFO(LOG_APP, "React Native lib ReactHarmony Init start...");
  napi_property_descriptor desc[] = {
      // { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }
    DECLARE_NAPI_FUNCTION("add", add),
    DECLARE_NAPI_FUNCTION("napiRunScriptFromArrayBuffer", napiRunScriptFromArrayBuffer),
    DECLARE_NAPI_FUNCTION("napiRunScriptFromFilePath", napiRunScriptFromFilePath)
    // DECLARE_NAPI_FUNCTION("testNapiRunAbc",testNapiRunAbc),
    // DECLARE_NAPI_FUNCTION("testGetPrototype", testGetPrototype)
  };
  // napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
  NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
  OH_LOG_INFO(LOG_APP, "React Native lib ReactHarmony Init end");
  return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "reactharmony",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterModule(void) {
  napi_module_register(&demoModule);
}
